﻿using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Shapes;

namespace YKXiangQi.Controls
{
    public class LineEx : FrameworkElement
    {
        protected override void OnRender(DrawingContext dc)
        {
            Point pos, tangent;
            double angleInRadians;
            double angleInDegrees;
            TransformGroup tg;

            var pen = new Pen(Stroke, StrokeThickness);
            var capPen = new Pen(Stroke, StrokeThickness - 2);
            dc.DrawGeometry(null, pen, LinePath);

            if (BeginCap != null)
            {
                try
                {
                    LinePath.GetPointAtFractionLength(0.01d, out pos, out tangent);
                    angleInRadians = Math.Atan2(tangent.Y, tangent.X) + Math.PI;
                    angleInDegrees = angleInRadians*180/Math.PI + 180;
                    tg = new TransformGroup();
                    tg.Children.Add(new RotateTransform(angleInDegrees));
                    LinePath.GetPointAtFractionLength(0.0d, out pos, out tangent);
                    tg.Children.Add(new TranslateTransform(pos.X, pos.Y));
                    dc.PushTransform(tg);
                    dc.DrawGeometry(Brushes.Red, capPen, BeginCap);
                    dc.Pop();
                }catch(Exception ex){}
            }
            
            if (EndCap != null)
            {
                try
                {
                    LinePath.GetPointAtFractionLength(0.99, out pos, out tangent);
                    angleInRadians = Math.Atan2(tangent.Y , tangent.X) + Math.PI;
                    angleInDegrees = angleInRadians * 180 / Math.PI;
                    tg = new TransformGroup();
                    tg.Children.Add(new RotateTransform(angleInDegrees));
                    LinePath.GetPointAtFractionLength(1, out pos, out tangent);
                    tg.Children.Add(new TranslateTransform(pos.X, pos.Y));
                    dc.PushTransform(tg);
                    dc.DrawGeometry(Brushes.Red, capPen, EndCap);
                }
                catch (Exception ex) { }
            }
        }

        protected override Size MeasureOverride(Size availableSize)
        {
            //TODO: Consider creating the Pen once when Stroke and StrokeThickness are set
            return LinePath.GetRenderBounds(new Pen(Stroke, StrokeThickness)).Size;
        }

        public static readonly DependencyProperty StrokeProperty = Shape.StrokeProperty.AddOwner(typeof(LineEx));
        public Brush Stroke
        {
            get { return (Brush)GetValue(StrokeProperty); }
            set { SetValue(StrokeProperty, value); }
        }

        public static readonly DependencyProperty StrokeThicknessProperty = Shape.StrokeThicknessProperty.AddOwner(typeof(LineEx));
        public double StrokeThickness
        {
            get { return (double)GetValue(StrokeThicknessProperty); }
            set { SetValue(StrokeThicknessProperty, value); }
        }

        public static readonly DependencyProperty LinePathProperty =
            DependencyProperty.Register("LinePath", typeof(PathGeometry), typeof(LineEx),
            new FrameworkPropertyMetadata(
                null,
                FrameworkPropertyMetadataOptions.AffectsRender, // choose appropriate flags here!!!
                LinePathChangedCallback));

        static void LinePathChangedCallback(DependencyObject sender, DependencyPropertyChangedEventArgs args)
        {
            var me = sender as LineEx;
            if (null != me)
            {
                me.OnLinePathChanged((PathGeometry)args.NewValue);
            }
        }

        public PathGeometry LinePath
        {
            get { return (PathGeometry)GetValue(LinePathProperty); }
            set { SetValue(LinePathProperty, value); }
        }

        public virtual void OnLinePathChanged(PathGeometry value)
        {
        }

        public static readonly DependencyProperty BeginCapProperty =
            DependencyProperty.Register("BeginCap", typeof(Geometry), typeof(LineEx),
            new FrameworkPropertyMetadata(
                null,
                FrameworkPropertyMetadataOptions.AffectsRender, // choose appropriate flags here!!!
                BeginCapChangedCallback));

        static void BeginCapChangedCallback(DependencyObject sender, DependencyPropertyChangedEventArgs args)
        {
            var me = sender as LineEx;
            if (null != me)
            {
                me.OnBeginCapChanged((Geometry)args.NewValue);
            }
        }

        public Geometry BeginCap
        {
            get { return (Geometry)GetValue(BeginCapProperty); }
            set { SetValue(BeginCapProperty, value); }
        }

        public virtual void OnBeginCapChanged(Geometry value)
        {
        }

        public static readonly DependencyProperty EndCapProperty =
            DependencyProperty.Register("EndCap", typeof(Geometry), typeof(LineEx),
            new FrameworkPropertyMetadata(
                null,
                FrameworkPropertyMetadataOptions.AffectsRender, // choose appropriate flags here!!!
                EndCapChangedCallback));

        static void EndCapChangedCallback(DependencyObject sender, DependencyPropertyChangedEventArgs args)
        {
            var me = sender as LineEx;
            if (null != me)
            {
                me.OnEndCapChanged((Geometry)args.NewValue);
            }
        }

        public Geometry EndCap
        {
            get { return (Geometry)GetValue(EndCapProperty); }
            set { SetValue(EndCapProperty, value); }
        }

        public virtual void OnEndCapChanged(Geometry value)
        {
        }
    }
}
